﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using Development.Tools;

namespace Development.Network.AsycnSocket
{
    /// <summary>
    /// 连接者
    /// </summary>
    public class AsyncUserToken
    {
        protected int m_linkId;                                //连接id
        protected AsyncSocketServer m_server;                   //服务器
        protected SocketAsyncEventArgs m_receiveEventArgs;   //接受异步
        protected SocketAsyncEventArgs m_sendEventArgs;     //发送异步
        protected DateTime m_ConnectDateTime;   //连接的时间
        protected DateTime m_ActiveDateTime;        //激活时间

        protected bool m_sendAsync; //标识是否有发送异步事件

        // 创建一个委托，返回类型为void
        public delegate void TokenCloseHandler(object sender);
        // 将创建的委托和特定事件关联,在这里特定的事件为KeyDown
        public TokenCloseHandler TokenCloseEvent;

        public int LinkId { get { return m_linkId; } }
        public SocketAsyncEventArgs ReceiveEventArgs { get { return m_receiveEventArgs; } set { m_receiveEventArgs = value; } }
        public SocketAsyncEventArgs SendEventArgs { get { return m_sendEventArgs; } set { m_sendEventArgs = value; } }
        public DateTime ConnectDateTime { get { return m_ConnectDateTime; } set { m_ConnectDateTime = value; } }
        public DateTime ActiveDateTime { get { return m_ActiveDateTime; } set { m_ActiveDateTime = value; } }


        protected DynamicBuffer m_receiveBuffer;
        protected DynamicBuffer m_sendBuffer;
        public DynamicBuffer ReceiveBuffer { get { return m_receiveBuffer; } set { m_receiveBuffer = value; } }
        public DynamicBuffer SendBuffer { get { return m_sendBuffer; } set { m_sendBuffer = value; } }


        protected byte[] m_asyncReceiveBuffer;     //接收缓存
        public byte[] AsyncReceiveBuffer { get { return m_asyncReceiveBuffer; } }

        protected Socket m_connectSocket;           //连接socket
        public Socket ConnectSocket
        {
            get
            {
                return m_connectSocket;
            }
            set
            {
                m_connectSocket = value;
                if (m_connectSocket == null) //清理缓存
                {
                    m_receiveBuffer.Clear();
                    m_sendBuffer.Clear();
                }
                m_receiveEventArgs.AcceptSocket = m_connectSocket;
                m_sendEventArgs.AcceptSocket = m_connectSocket;
            }
        }


        public AsyncUserToken(int asyncReceiveBufferSize, AsyncSocketServer server)
        {
            m_connectSocket = null;
            m_receiveEventArgs = new SocketAsyncEventArgs();
            m_receiveEventArgs.UserToken = this;
            m_asyncReceiveBuffer = new byte[asyncReceiveBufferSize];
            m_receiveEventArgs.SetBuffer(m_asyncReceiveBuffer, 0, m_asyncReceiveBuffer.Length);
            m_sendEventArgs = new SocketAsyncEventArgs();
            m_sendEventArgs.UserToken = this;
            m_receiveBuffer = new DynamicBuffer(asyncReceiveBufferSize);
            m_sendBuffer = new DynamicBuffer(asyncReceiveBufferSize);
            m_server = server;
            m_sendAsync = false;
        }


        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer"></param>
        public void SendMsg(byte[] buffer)
        {
            lock (this)
            {
                if (m_connectSocket == null || m_server == null)
                {
                    return;
                }

                m_sendBuffer.WriteBuffer(buffer);
                PostSend();
            }

        }


        protected void PostSend()
        {
            if (m_sendAsync)
            {
                return;
            }

            if (m_sendBuffer.DataCount > 0)
            {
                m_sendAsync = true;
                m_sendEventArgs.SetBuffer(m_sendBuffer.Buffer, 0, m_sendBuffer.DataCount);
                bool willRaiseEvent = m_connectSocket.SendAsync(m_sendEventArgs);
                if (!willRaiseEvent)
                {
                    m_server.SendAsyncEvent(m_connectSocket, m_sendEventArgs);
                }
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer"></param>
        public void SendMsg(byte[] buffer, int offset, int count)
        {
            lock (this)
            {
                if (m_connectSocket == null || m_server == null)
                {
                    return;
                }
                m_sendBuffer.WriteBuffer(buffer, offset, count);
                PostSend();
            }
        }

        /// <summary>
        /// 发送完成
        /// </summary>
        public void SendCompleted(int count)
        {
            m_sendBuffer.Clear(count);
            if (m_sendBuffer.DataCount > 0)
            {
                m_sendEventArgs.SetBuffer(m_sendBuffer.Buffer, 0, m_sendBuffer.DataCount);
                bool willRaiseEvent = m_connectSocket.SendAsync(m_sendEventArgs);
                if (!willRaiseEvent)
                {
                    m_server.SendAsyncEvent(m_connectSocket, m_sendEventArgs);
                }
            }
            else
            {
                m_sendAsync = false;
            }

        }

        /// <summary>
        /// 关闭token
        /// </summary>
        public void CloseToken()
        {
            m_server.CloseClientSocket(this);
        }

        public void Clear()
        {
            if (m_connectSocket != null)
            {
                m_connectSocket.Close();
                m_connectSocket = null;
            }
            m_receiveBuffer.Clear();
            m_sendBuffer.Clear();
            if (TokenCloseEvent != null)
            {
                TokenCloseEvent(this);
                TokenCloseEvent = null;
            }
        }

        public static AsyncUserToken CreateUserToken(int recvSendBuffSize, AsyncSocketServer server)
        {
            AsyncUserToken userToken = new AsyncUserToken(recvSendBuffSize, server);
            userToken.m_linkId = GUIDTool.LinkId;
            return userToken;
        }


    }
}
